[ARC064F]Rotated Palindromes

2019-11-05
Atcoder

题意

求所有每位的数字为$1~k$,长度为$n$的回文串,任意次将第一个数字放到最后一个所形成的不同的序列数量

题解

先考虑循环节,如果循环节长度为奇数,那么贡献为$len$

如果长度为偶数,那么贡献为$(len/2)$

令$f_i$为最小循环节长度为$i$的数量,dp即可

调试记录

1ll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <cstdio>
#include <vector>
#include <algorithm>
const int mo = 1e9 + 7;
using namespace std;
int pow(int x, int t){
int res = 1;
while (t > 0){
if (t & 1) res = 1ll * res * x % mo;
x = 1ll * x * x % mo;
t >>= 1;
}
return res;
}
int n, k, dp[10001]; vector <int> p;
int main(){
scanf("%d%d", &n, &k);
for (int i = 1; i * i <= n; i++){
if (n % i == 0){
p.push_back(i);
if (i * i != n) p.push_back(n / i);
}
}
sort(p.begin(), p.end()); int ans = 0;
for (int i = 0; i < p.size(); i++){
dp[i] = pow(k, (p[i] + 1) >> 1);
for (int j = 0; j < i; j++)
if (p[i] % p[j] == 0) dp[i] = (dp[i] - dp[j] + mo) % mo;
ans = (ans + 1ll * dp[i] * (p[i] / (1 + (p[i] % 2 == 0))) % mo) % mo;
}
printf("%d\n", ans);
return 0;
}